Service providers
公式ドキュメント
概要
Laravelアプリケーションのbootstrapに責任を持つ
Service providersによって、すべてのLaravelのコアサービスと自作のアプリケーションがbootstrapされる bootstrapとは、次のようなものをregisterすること
sercive container binding
event listener
middleware
router
LaravelにはどんなService Providerがロードされるのか
config/app.phpのprovidersarrayに自作アプリケーションでロードするservice provideのリストがある その多くがdeferredなproviderで、すべてのリクエストで毎回ロードされるわけではなく、必要なときのみロードされる。
自作のService Providersを書く
ServiceProviderクラスを書く
Illuminate\Support\ServiceProviderを継承しregister()とboot()をもつ
Service Providerのメソッドの呼ばれる順序
1. 全Providerのregister()
2. 全Providerのboot()
この順序が担保されているため、bootの中では$appが使える
$appはほかのService ProviderでbindingがすんだService containerが利用できるオブジェクト
register()
インタフェースにインスタンスをbindするのが典型的な使い方kadoyau.icon
注意:それ以外のいかなるevent listenerやroutesや機能の一部をかいてはいけない
まだロードしていないサービスを意図せずService Providerから使うことを防ぐため
boot()
This method is called after all other service providers have been registered, meaning you have access to all other services that have been registered by the framework:
code:php
public function boot(ResponseFactory $response)
{
$response->macro('caps', function ($value) {
//
});
}
bindingsとsingletons
service providerで単純なbindingをたくさんregisterするときに便利な機能
service providerがロードされる時点でプロパティがチェックされて結合を登録する
使わない場合
code:php
$this->app->bind(
ServerProvider::class, // インタフェース
DigitalOceanServerProvider::class //実装クラス
);
使う場合
code:php
class AppServiceProvider extends ServiceProvider
{
/**
* 登録する必要のある全コンテナbinding
*
* @var array
*/
public $bindings = [
ServerProvider::class => DigitalOceanServerProvider::class,
];
サービスプロバイダを登録する
Service Providerを書きおわったら、 config/app.phpに登録する
プロバイダを追加する際にはこの配列に追加する
1. deferredServices配列にdifferedされるServiceProviesを登録する
たぶんこれがbootstrapPath().'/cache/services.phpに保存されるkadoyau.icon
2. differedなサービスプロバイダを初期化する
\Illuminate\Foundation\Bootstrap\RegisterProvidersを含む
$bootstrappersに登録されたbootstrap classが上から順に実行される
getCachedServicesPath()が返す実態は$this->bootstrapPath().'/cache/services.php'
このファイルにはprovidersやdeferredなどの配列が定義されている
code:services.php
<?php return array (
'providers' => array (
0 => 'Illuminate\\Auth\\AuthServiceProvider',
1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
2 => 'Illuminate\\Bus\\BusServiceProvider',
// 省略
),
'deferred' => array (
'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
// 省略
),
ここまではアプリケーションの初期化プロセスで行われる。まだ実態は作られていないことに注意
実際に使うときがくると、Illuminate\Foundation\Application->loadDeferredProvider()からregisterDeferredProvider()が呼ばれ、前記services.phpで定義されているdeferredなServiceProviders(BroadcastManagerとか)が初期化される 各Service Providerのregister()やboot()が呼ばれて、インタフェースに対する具象クラスを作成する
これはどこかから呼ばれる?
$bootstrappersの最後にIlluminate\Foundation\Bootstrap\BootProvidersのbootstrap()が呼び出されることで Illuminate\Contracts\Foundation\Application->boot()が呼び出される 各ServiceProviderのboot()メソッドが順次呼び出される
Deferred Provider
Laravelはdefferedなサービスプロバイダによって提供されるサービスの一覧をコンパイルして、サービスプロバイダの名前とともに保存している。実際にサービスのうちの一つが必要になったときに、サービスプロバイダをロードする